/*
 * PhotonRTOS础光实时操作系统 -- 异步功能实现文件
 *
 * Copyright (C) 2022 国科础石(重庆)软件有限公司
 *
 * 作者: Jiayuan Liang <liangjiayuan@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */

#include <autosar/internal.h>

static void try_to_call_error_hook(int service_id, int task_nr, int status)
{
	if (status == E_OK)
		return;
	if (osek_tasks[task_nr].state != SUSPENDED) {
		if (service_id == OSServiceId_ActivateTaskAsyn)
			osek_call_hook_0(ActivateTaskAsyn, status);
	else if (service_id == OSServiceId_SetEventAsyn)
		osek_call_hook_0(SetEventAsyn, status);
	}
}


/**
 * (autosar cp)相关，判断存在其它核上的cp任务想要异步激活当前核上的任务,如果有则完成异步激活功能。
 */
static void cp_check_need_active(void)
{
    int i, j;
    unsigned long flag;
    unsigned char status;
    struct process_desc *pro_desc;
    uint32_t app_id, trusted_func_app_id;


    /**
     * core_need_activate()判断 该核上是否存在任务被其他核上的cp任务异步激活。
     */
    smp_lock_irqsave(&activate_task_async_lock, flag);
    if (core_need_activate()) {
        for (i = 0; i <OS_NR_TASK; i++) {
            if (osek_tasks[i].stack == NULL)
                continue;

            if (smp_processor_id() == osek_tasks[i].core_id
                && task_need_async_activate(&osek_tasks[i])) {

                for (j = 0; j <OS_NR_TASK; j++) {
                    if (osek_tasks[j].stack == NULL)
                        continue;
                    if (osek_tasks[i].cp_attr.async_activate_caller[j/8] & (1 << (j % 8))) {
                        /**
                         * 获取想要异步激活osek_tasks[i]的osek_tasks[j]
                         */
                        pro_desc = osek_tasks[j].stack;
                        app_id = pro_desc->object.app_id;
                        trusted_func_app_id =
                            pro_desc->object.trusted_func_app_id;
                        /**
                         * 因为调用CallTrustedFunction()的时候，所属的app_id要变成trusted_func所属的trusted_func_app_id。
                         */

                        status = autosar_activate_task_async(i,
                            trusted_func_app_id != INVALID_OSAPPLICATION ? trusted_func_app_id : app_id);
                        try_to_call_error_hook(OSServiceId_ActivateTaskAsyn, j, status);

                        osek_tasks[i].cp_attr.async_activate_caller[j] &= ~(1 << (j % 8));
                    }
                }
                clear_task_activate_async_flag(&osek_tasks[i]);
            }
        }
        clear_core_activate();
    }
    smp_unlock_irqrestore(&activate_task_async_lock, flag);
}

/**
 * (autosar cp)相关，判断存在其它核上的cp任务想要异步对该核上的任务设置事件，如果有就完成异步设置事件功能。
 */
static void cp_check_need_set_event(void)
{
    int i, j;
    unsigned long flag;
    unsigned char status;
    struct process_desc *pro_desc;
    uint32_t app_id, trusted_func_app_id;
    /**
     * core_need_activate()判断 该核上是否存在任务被其他核上的cp任务异步激活。
     */
    smp_lock_irqsave(&set_event_async_lock, flag);
    if (core_need_set_event()) {

        for (i = 0; i <OS_NR_TASK; i++) {
            if (osek_tasks[i].stack != NULL &&
                smp_processor_id() == osek_tasks[i].core_id
                && task_need_async_set_event(&osek_tasks[i])) {
                for (j = 0; j <OS_NR_TASK; j++) {
                    if (osek_tasks[j].stack != NULL &&
                        osek_tasks[i].cp_attr.async_set_event_caller[j].event_mask != 0) {
                        /**
                         * 获取想要异步给osek_tasks[i]设置事件的osek_tasks[j]
                         */
                        pro_desc = osek_tasks[j].stack;
                        app_id = pro_desc->object.app_id;
                        trusted_func_app_id = pro_desc->object.trusted_func_app_id;

                        /**
                         * 因为调用CallTrustedFunction()的时候，
                         * 所属的app_id要变成trusted_func所属的trusted_func_app_id。
                         */
                        status = autosar_set_event_async(i,
                            osek_tasks[i].cp_attr.async_set_event_caller[j].event_mask,
                            trusted_func_app_id != INVALID_OSAPPLICATION ? trusted_func_app_id : app_id);
                        try_to_call_error_hook(OSServiceId_SetEventAsyn, j, status);

                        osek_tasks[i].cp_attr.async_set_event_caller[j].event_mask = 0;
                    }
                }
                clear_task_event_async_flag(&osek_tasks[i]);
            }
        }
        clear_core_set_event_flag();
    }
    smp_unlock_irqrestore(&set_event_async_lock, flag);
}

void os_check_async_action(void)
{
    cp_check_need_active();
	cp_check_need_set_event();
}
